﻿#region usings
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;

using ArcannEngine.Entities;
using ArcannEngine;
#endregion

namespace ArcannEngine.Components
{
    public class GameInputComponent : Component
    {
        #region Description
        /*--------------------------------------*/
        /*            Obsluga klawiszy          */
        /*--------------------------------------*/
        /* W/S - przod/tyl                      */
        /* A/D - lewo/prawo                     */
        /* Q/E - obrot lewo/prawo               */
        /* Z/X - zmniejsz/zwieksz czulosc       */
        /* SPACJA - skok                        */
        /* C - wylaczanie sterowania(widok fpp) */
        /*--------------------------------------*/
        #endregion

        #region Fields

        private MotionMath motionMath;
        private GamePadState gamepadState;
        private GamePadState oldGamepadState;
        private KeyboardState keyboardState;
        private KeyboardState oldKeyboardState;
        private Entity parentEntity;
        private bool moveAllowed;
        private float speed;
        public Vector3 direction;
        public Matrix cameraDirection;
        //private bool rotatedX;
        //private bool rotatedY;


        #endregion

        #region Accessors
        protected override string GetName()
        {
            return "Controls";
        }
        #endregion

        #region Ctor
        public GameInputComponent(Entity parentEntity)
            : base(parentEntity)
        {
            this.motionMath = new MotionMath();
            this.Initialize();
            this.parentEntity = parentEntity;
            this.moveAllowed = true;
            this.speed = 10.0f;
            //this.direction = Vector3.Backward;
            this.direction = Vector3.Zero;
        }
        #endregion

        #region Update

        public override void Update(GameTime gameTime)
        {
            this.Flush();
            this.keyboardState = Keyboard.GetState();
            this.gamepadState = GamePad.GetState(PlayerIndex.One);

            Keys[] k = keyboardState.GetPressedKeys();
            int count = keyboardState.GetPressedKeys().Count();
        
            if (this.KeyPressed(Keys.C))
            {
                this.moveAllowed = !this.moveAllowed;
            }

            if (this.moveAllowed == true)
            {
                if (this.gamepadState.IsConnected == true)
                {
                    this.HandleGamePad();
                }
                else if (count > 0)
                {
                    this.HandleKeyboard();
                }
            }
            this.parentEntity.position += -this.speed * this.direction;
            this.direction *= new Vector3(0.95f, 0.95f, 0.95f);
           /* this.direction.X *= 0.95f;
            this.direction.Y *= 0.95f;
            this.direction.Z *= 0.95f;*/
            this.Flush();
        }
        #endregion

        #region Initialize
        protected override void Initialize()
        {
            base.Initialize();
        }
        #endregion

        #region GamePad Handle
        private void HandleGamePad()
        {
            if (this.gamepadState.ThumbSticks.Left.X != 0 || this.gamepadState.ThumbSticks.Left.Y != 0)
            {
                parentEntity.rotation = Matrix.CreateWorld(Vector3.Zero, -EngineCommon.camDirection, Vector3.Up);
                //this.motionMath.Strafe(ref this.parentEntity.position, ref this.parentEntity.rotation, -gamepadState.ThumbSticks.Left.X * speed);
                this.motionMath.Walk(ref this.parentEntity.position, ref this.parentEntity.rotation, -gamepadState.ThumbSticks.Left.Y * speed);
            }
            if (this.ButtonPressed(Buttons.A))
            {
                this.motionMath.Jump(ref this.parentEntity.position, ref this.parentEntity.rotation, -speed * 10.0f);
            }
            //this.motionMath.YawAroundWorldUp(ref this.parentEntity.rotation, -gamepadState.ThumbSticks.Right.X / 10);
            if (this.ButtonDown(Buttons.LeftTrigger))
            {
                this.speed *= 0.95f;
            }
            else if (this.ButtonDown(Buttons.RightTrigger))
            {
                this.speed *= 1.05f;
            }
            
        }
        #endregion

        #region Keyboard Handle
        private void HandleKeyboard()
        {
            int count = keyboardState.GetPressedKeys().Count();

            if (KeyDown(Keys.W) || KeyDown(Keys.A) || KeyDown(Keys.S) || KeyDown(Keys.D))
            {
                this.cameraDirection = Matrix.CreateWorld(Vector3.Zero, EngineCommon.camDirection, Vector3.Up);

                // Dodawanie wektorow kierunku, zeby w kazdym isc z ta sama predkoscia
                // wczesniej po skosie szlo sie 2 razy szybciej niz prosto
                this.direction = Vector3.Zero;
                /*   if (!((keyboardState.GetPressedKeys().Contains(Keys.W) && keyboardState.GetPressedKeys().Contains(Keys.S))
                    || (keyboardState.GetPressedKeys().Contains(Keys.A) && keyboardState.GetPressedKeys().Contains(Keys.D))))*/
               
                if (this.KeyDown(Keys.W) && this.KeyDown(Keys.S)) return;
                else if (this.KeyDown(Keys.A) && this.KeyDown(Keys.D)) return;
                else
                {
                    if (KeyDown(Keys.W))
                    {
                        direction += cameraDirection.Backward;
                    }
                    if (KeyDown(Keys.S))
                    {
                        direction += cameraDirection.Forward;
                    }
                    if (KeyDown(Keys.A))
                    {
                        direction += cameraDirection.Right;
                    }
                    if (KeyDown(Keys.D))
                    {
                        direction += cameraDirection.Left;
                    }

                    direction.Normalize();
                    if (direction.Length() != 0)
                    {
                        this.parentEntity.rotation = Matrix.CreateWorld(Vector3.Zero, direction, Vector3.Up);
                    }
                }
            }

            //if (this.KeyDown(Keys.W)) 
            //{
            //    parentEntity.rotation = Matrix.CreateWorld(Vector3.Zero, -EngineCommon.camDirection, Vector3.Up);
            //    this.motionMath.Walk(ref this.parentEntity.position, ref this.parentEntity.rotation, -speed);
            //}
            //if (this.KeyDown(Keys.S))
            //{
            //    parentEntity.rotation = Matrix.CreateWorld(Vector3.Zero, EngineCommon.camDirection, Vector3.Up);
            //    this.motionMath.Walk(ref this.parentEntity.position, ref this.parentEntity.rotation, -speed);
            //}
            //if (this.KeyDown(Keys.A))
            //{
            //    parentEntity.rotation = Matrix.CreateWorld(Vector3.Zero, -EngineCommon.camDirection, Vector3.Up);
            //    //parentEntity.rotation.Left();
            //    this.motionMath.Strafe(ref this.parentEntity.position, ref this.parentEntity.rotation, speed);
            //}
            //if (this.KeyDown(Keys.D))
            //{
            //    parentEntity.rotation = Matrix.CreateWorld(Vector3.Zero, -EngineCommon.camDirection, Vector3.Up);
            //    this.motionMath.Strafe(ref this.parentEntity.position, ref this.parentEntity.rotation, -speed);
            //}
            //if (this.KeyDown(Keys.Q))
            //{
            //    this.motionMath.Yaw(ref this.parentEntity.rotation, speed / 2 * 0.01f);
            //}
            //if (this.KeyDown(Keys.E))
            //{
            //    this.motionMath.Yaw(ref this.parentEntity.rotation, -speed / 2 * 0.01f);
            //}
            if (this.KeyDown(Keys.X))
            {
                speed *= 1.05f;
            }
            if (this.KeyDown(Keys.Z))
            {
                speed *= 0.95f;
            }
            if (this.KeyPressed(Keys.P))
            {
                World.stopped = !World.stopped;
            }
            if (this.KeyPressed(Keys.L))
            {
                World.slowMo = !World.slowMo;
            }
            if (this.KeyPressed(Keys.Y))
            {
                Console.WriteLine(Parent.position);
            }

        }
        #endregion

        #region Methods
        private void Flush()
        {
            this.oldKeyboardState = this.keyboardState;
            this.oldGamepadState = this.gamepadState;
        }
        #endregion

        #region Keyboard Methods

        private bool KeyReleased(Keys key)
        {
            return  this.keyboardState.IsKeyUp(key) && this.oldKeyboardState.IsKeyDown(key);
        }
        private bool KeyPressed(Keys key)
        {
            return this.keyboardState.IsKeyDown(key) &&
             this.oldKeyboardState.IsKeyUp(key);
        }

        private bool KeyDown(Keys key)
        {
            return this.keyboardState.IsKeyDown(key);
        }
        #endregion

        #region GamePad Methods
        private bool ButtonReleased(Buttons button)
        {
            return this.gamepadState.IsButtonUp(button) &&
             this.oldGamepadState.IsButtonDown(button);
        }
        private bool ButtonPressed(Buttons button)
        {
            return this.gamepadState.IsButtonDown(button) &&
             this.oldGamepadState.IsButtonUp(button);
        }
        private bool ButtonDown(Buttons button)
        {
            return this.gamepadState.IsButtonDown(button);
        }
        #endregion
    }
}
